<?php

declare (strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */

namespace App\Service\User;

use App\Dao\BusinessDao;
use App\Dao\CouponDao;
use App\Dao\UserBusinessFavDao;
use App\Exception\CustomException;
use App\Service\Service;

use Hyperf\Di\Annotation\Inject;

/**
 * 商家服务
 *
 * @author 刘兴永(aile8880@qq.com)
 * @package App\Service\Admin
 */
class BusinessService extends Service
{
    /**
     * @Inject
     * @var BusinessDao
     */
    public $dao;

    /**
     * @Inject
     * @var CouponDao
     */
    public $coupon_dao;

    /**
     * @Inject
     * @var UserBusinessFavDao
     */
    public $user_business_dao;

    /**
     * 店铺详情
     *
     * @param int $business_id
     * @return mixed
     */
    public function store( int $business_id )
    {

        $data = $this->geoCalculatorOne(0, 114.082581,22.624509, $business_id);

        $business_count = $this->user_business_dao->count([
            'business_id' => $business_id
        ]);

        $data['business_count'] = $business_count;

        if( $data['enable_coupon'] == '1' ) {
            $data['coupon'] = $this->coupon_dao->getList(1,[
                'business_id' => $business_id
            ], 'created_at desc');
        }

        if( $data['enable_voucher'] == '1' ) {
            $data['coupon'] = $this->coupon_dao->getList(2,[
                'business_id' => $business_id
            ], 'created_at desc');
        }

        if( $data['enable_full_discount'] == '1' ) {
            $data['coupon'] = $this->coupon_dao->getList(3,[
                'business_id' => $business_id
            ], 'created_at desc');
        }

        return $data;
    }

    /**
     * 以用户为中心，计算用户在某城市范围内附近的商家列表
     * 此方法带有缓存机制，在注入了UserMiddleware中间件的控制器调用此方法则会自动缓存结果
     * 否则每次都会实时调用
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param array $businessIds 商家id
     * @return mixed
     */
    public function geoCalculator(int $city_id, float $longitude, float $latitude, array $businessIds = [])
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
        try {
            $user_id = uid();

            // 从缓存中返回
            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id;
            $result = $this->redis->get($nearbyBusinessRedisKey);
            if ($result) {
                var_dump('我是从缓存中读取的');
                return json_decode($result, true);
            }
        }
        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = ['in', $businessIds];
        $city_id > 0 && $map['city_id'] = $city_id;

        // 获取商家列表
        $business_list = $this->dao->getBusinessList($map);

        if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);
        foreach ($business_list as $key => $business) {
            $this->redis->rawCommand('geoadd', $redis_key, $business->longitude, $business->latitude, $business->id);
        }

        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            foreach ($business_list as $key => $business) {
                if ($geo[0] != $business->id) continue;
                $business_list[$key]['distance'] = $geo[1];
                $business_list[$key]['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';

                if( $business['enable_coupon'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(1,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

                if( $business['enable_voucher'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(2,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }

                if( $business['enable_full_discount'] == '1' ) {
                    $business_list[$key]['coupon'] = $this->coupon_dao->getList(3,[
                        'business_id' => $business->id
                    ], 'created_at desc');
                }
            }
        }

        if (null !== $businessIds) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list), 60 * 10);
            }
            catch (CustomException $e) {}
        }

        return $business_list->toArray();
    }

    /**
     * 通过店铺ID去查询数据
     *
     *
     *
     * @param int $city_id 城市ID，0代表不筛选城市
     * @param float $longitude 经度
     * @param float $latitude 纬度
     * @param int $businessIds 商家id
     * @return mixed
     */
    public function geoCalculatorOne(int $city_id, float $longitude, float $latitude, int $businessIds)
    {
        // 使用try接管中间件异常，可以根据用户登录情况做出灵活的缓存策略
        try {
            $user_id = uid();

            // 从缓存中返回
            $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id.':business_id'.$businessIds;
            $result = $this->redis->get($nearbyBusinessRedisKey);
            if ($result) {
                var_dump('我是从缓存中读取的');
                return json_decode($result, true);
            }
        }
        catch (CustomException $e) {}

        // 用户未登录或者缓存不存在。实时计算

        $map = [];
        !empty($businessIds) && $map['id'] = $businessIds;
        $city_id > 0 && $map['city_id'] = $city_id;

        // 获取商家列表
        $business_list = $this->dao->getBusinessFirst($map);

       // if (count($business_list) === 0) return $business_list;

        // 数据导入redis
        $redis_key = 'geoBusiness:' . $longitude . ',' . $latitude;
        $this->redis->del($redis_key);

        $this->redis->rawCommand('geoadd', $redis_key, $business_list['longitude'], $business_list['latitude'], $business_list['id']);

        // 获取2000公里中心范围内的数据
        // 并将redis计算结果并入原有的结果集
        // 将距离结果以友好的方式记录并展示
        $geo_result = $this->redis->rawCommand('georadius', $redis_key, $longitude, $latitude, '2000000', 'm', 'WITHDIST');
        foreach ($geo_result as $geo) {
            if ($geo[0] != $business_list['id']) continue;
            $business_list['distance'] = $geo[1];
            $business_list['distance_desc'] = $geo[1] >= 1000 ? floor(($geo[1] / 1000) * 10) / 10 . 'km' : (int)$geo[1] . 'm';
        }

        if (null !== $businessIds) {
            try {
                $user_id = uid();

                // 将结果缓存起来，暂时设置缓存10分钟，后续考虑设置为更合理的数值
                $nearbyBusinessRedisKey = 'nearbyBusiness:user_id' . $user_id . ':city_id' . $city_id.':business_id'.$businessIds;
                $this->redis->set($nearbyBusinessRedisKey, json_encode($business_list), 60);
            }
            catch (CustomException $e) {}
        }

        return $business_list->toArray();
    }
}